package com.easypay.util;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * Aes 加密算法
 *
 * @date: 2021/10/17 10:31
 * @author: pandans
 */
public class AesUtil {
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS5Padding";

    /**
     * 易生测试公钥， 用来加密商户的aes密钥. 生产上注意更换此密钥
     */
    public static final String EASYPAY_PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAqRw0nZ1rGTpAeKupP7coS+en6BveJL4aFVt9men4Zzkpuv/IeK6YJ2yk4m8ppZ7TLW4t5WsPEhYOnUfMtjhW4nuQfjgU54juJ1KMHYiX9gaaO+z80ZnaiKD2YsZMFiE9dlTeBlkRL5xXbHa+JonHfVKXMr13oI8oZNKdpnvknQIDAQAB";


    /**
     * @param src: 源数据
     * @param key: Aes加密密钥
     * @return 加密后数据
     * @Description 使用AES算法对数据进行加密后使用base64编码
     * @date: 2021/10/17 10:49
     * @author: pandans
     */
    public static String encrypt(String src, String key) {
        if (key == null) {
            System.out.print("Aes Key为空null");
            return null;
        }
        try {
            byte[] raw = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
            //"算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));
            return Base64.encode2String(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * @param src: AES加密后Base64编码的数据
     * @param key: AES密钥
     * @return 原数据
     * @Description 使用AES算法解密得到原数据内容
     * @date: 2021/10/17 10:53
     * @author: pandans
     */
    public static String decrypt(String src, String key) {
        if (key == null) {
            System.out.print("AES Key为空null");
            return null;
        }
        try {
            byte[] raw = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            //先用base64解密
            byte[] encrypted1 = Base64.decode2Byte(src);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, StandardCharsets.UTF_8);
            return originalString;
        } catch (Exception ex) {
            System.out.println(ex);
            return null;
        }
    }


    /**
     * 生成数字信封
     * @param aesKey
     * @param easyPubKey
     * @return
     */
    public static String dgtlEnvelp(String aesKey, String easyPubKey) {
        return RsaUtil.encryptWithPKCS1(aesKey, easyPubKey);
    }

    /**
     * 随机生成秘钥
     */
    public static String getKey() {
        try {
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            kg.init(128);
            //要生成多少位，只需要修改这里即可128, 192或256
            SecretKey sk = kg.generateKey();
            byte[] b = sk.getEncoded();
            String s = byteToHexString(b);
            System.out.println(s);
            System.out.println("十六进制密钥长度为" + s.length());
            System.out.println("二进制密钥的长度为" + s.length() * 4);
            return s;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.out.println("没有此算法。");
            return null;
        }
    }

    /**
     * 使用指定的字符串生成秘钥
     */
    public static void getKeyByPass() {
        //生成秘钥
        String password = "easypay";
        try {
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            // kg.init(128);//要生成多少位，只需要修改这里即可128, 192或256
            //SecureRandom是生成安全随机数序列，password.getBytes()是种子，只要种子相同，序列就一样，所以生成的秘钥就一样。
            kg.init(128, new SecureRandom(password.getBytes()));
            byte[] b = kg.generateKey().getEncoded();
            String s = byteToHexString(b);
            System.out.println(s);
            System.out.println("十六进制密钥长度为" + s.length());
            System.out.println("二进制密钥的长度为" + s.length() * 4);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.out.println("没有此算法。");
        }
    }

    /**
     * byte数组转化为16进制字符串
     *
     * @param bytes
     * @return
     */
    public static String byteToHexString(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String strHex = Integer.toHexString(bytes[i]);
            if (strHex.length() > 3) {
                sb.append(strHex.substring(6));
            } else {
                if (strHex.length() < 2) {
                    sb.append("0" + strHex);
                } else {
                    sb.append(strHex);
                }
            }
        }
        return sb.toString();
    }


    public static void main(String[] args) {
        String key = getKey();
//        System.out.println(key);
//        String encode = encrypt("1111", key);
//        System.out.println(encode);
//        String decode = decrypt(encode, key);
//        System.out.println(decode);

        String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWzfgbAcHjIvQ9BMkqqM0av7a2QK+tnQYaF0aQVrG3Dc+cLuMYKx6EOuwnAha+6dHw8froCITXTjiBchZ0hYmhDZE3zbbXJxtJasT4/B8yOPerexWeuk7L5DuM9CzNoxXhhv0qeQ1cKvniBQJkkkSAgcIp+9WPsgZK7KYyzy12+QIDAQAB";
        String priKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJbN+BsBweMi9D0EySqozRq/trZAr62dBhoXRpBWsbcNz5wu4xgrHoQ67CcCFr7p0fDx+ugIhNdOOIFyFnSFiaENkTfNttcnG0lqxPj8HzI496t7FZ66TsvkO4z0LM2jFeGG/Sp5DVwq+eIFAmSSRICBwin71Y+yBkrspjLPLXb5AgMBAAECgYEAjPz9o4ouEcPBIjcSOB7eus5X7OZnGGKArO3r29AhkCmKWtN/Hz5Y5nkMBaAvUcfarnAdCsfEImMP8v2NvtyGASv+UaO6X8yKQyu8xuGy1UEWTsjmUzTH8F395N++0NhBZZJGqZW7Rapb17AFl8QKfuGvi2AXsg7iZ8c2Jh9n7DECQQDFsuNKke1R9VBjMxqWwh80ozUAjhfEAnZA5laItZ00P2HDZx5Wuaf9Nai7F256Fa054ueq0tNPwFqWVNUeEV/dAkEAw0bXB4iFz+APky3VKQUFD+wGrKVd/qus4eh2ySy09Jz5k0+JkKGHW2XyliSapPo4/SoywRsxtmgnuXYw3cDPzQJAAS0tWRZBOUmibtSxBdCl6uRFvnkZ/xqcpYo5XZrnEpaF+Gm2roFwVHtrQ6HCEIvsefm1sziJ9WGJqHdcxU8JKQJAUSXFAapoAORZVI39QJiHbABnHaNylfv9UbtqcVsUr3nz9JVe0y1stDx/PIllgh1BRWMdyEVmuSg7KcTFtcEEGQJAcOQX+7UD9LrUx2WXCmW0Xb8UJBArVZBVA2x5w70W8TladI4X02r/4zXzJJJR5wvIUdSIw3CS+oLGS1VnWwSGRg==";
        String dgt = dgtlEnvelp(key, pubKey);
        System.out.println(dgt);

        String src = RsaUtil.decryptWithPKCS1(dgt, priKey);

        System.out.println(src);
    }
}
